#set( $symbol_pound = '#' )
#set( $symbol_dollar = '$' )
#set( $symbol_escape = '\' )
package ${package}.common.validator;

import com.google.common.collect.Sets;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.Set;
import ch.qos.logback.classic.Logger;

/**
 * Description: 枚举类入参校验器
 *
 * @author wenxiaopeng
 * @date 2021/1/9 09:51
 *
 * <pre>
 *              ${copyright}
 *      Copyright (c) 2019. All Rights Reserved.
 * </pre>
 */
@Documented
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = EnumValidator.Guarder.class)
public @interface EnumValidator {
    Logger log = (Logger) LoggerFactory.getLogger(EnumValidator.class);

    String message() default "错误的字段取值";

    Class<?>[] groups() default {};

    Class<? extends Enum> accept();

    String field() default "type";

    boolean nullable() default true;

    Class<? extends Payload>[] payload() default {};

    class Guarder implements ConstraintValidator<EnumValidator, Object> {

        private final Set<Object> values = Sets.newHashSet();

        private boolean nullable;

        @Override
        public void initialize(EnumValidator constraintAnnotation) {

            Class<? extends Enum> accept = constraintAnnotation.accept();
            nullable = constraintAnnotation.nullable();
            Assert.isTrue(accept.isEnum(), "Wrong Class");
            String field1 = constraintAnnotation.field();
            Enum[] enumConstants = accept.getEnumConstants();
            try {
                Field f = accept.getDeclaredField(field1);
                f.setAccessible(true);
                for(Enum field : enumConstants){
                    values.add(f.get(field).toString());
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
                log.error("error info" ,e);
            }
        }

        @Override
        public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {

            if (o == null) {
                return nullable;
            }
            return values.contains(o.toString());
        }
    }

}
